package com.merry.aop.advisor;

import java.io.Serializable;

import org.aopalliance.aop.Advice;

import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
import org.springframework.aop.support.AbstractGenericPointcutAdvisor;
import org.springframework.core.Ordered;
import org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor;
import org.springframework.lang.Nullable;
import org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor;
import org.springframework.util.ObjectUtils;

/**
 * 一个 {@link PointcutAdvisor} 接口的基本实现抽象类。它有以下几个子类
 * <li>{@link AbstractGenericPointcutAdvisor} 这是一个通用的子抽象类。
 * <li>{@link TransactionAttributeSourceAdvisor} 这个子类是专门处理事务的。
 * <li>{@link PersistenceExceptionTranslationAdvisor} 这个子类是专门处理DAO的。
 * <li>{@link AspectJPointcutAdvisor} 这个类是专门处理 Aspect相关注解的，不是它的子类，而是它的抽象类。
 *
 */
@SuppressWarnings("serial")
public abstract class AbstractPointcutAdvisor implements PointcutAdvisor, Ordered, Serializable {

    @Nullable
    private Integer order;


    public void setOrder(int order) {
        this.order = order;
    }

    @Override
    public int getOrder() {
        if (this.order != null) {
            return this.order;
        }
        Advice advice = getAdvice();
        if (advice instanceof Ordered) {
            return ((Ordered) advice).getOrder();
        }
        return Ordered.LOWEST_PRECEDENCE;
    }

    @Override
    public boolean isPerInstance() {
        return true;
    }


    @Override
    public boolean equals(@Nullable Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof PointcutAdvisor)) {
            return false;
        }
        PointcutAdvisor otherAdvisor = (PointcutAdvisor) other;
        return (ObjectUtils.nullSafeEquals(getAdvice(), otherAdvisor.getAdvice()) &&
                ObjectUtils.nullSafeEquals(getPointcut(), otherAdvisor.getPointcut()));
    }

    @Override
    public int hashCode() {
        return PointcutAdvisor.class.hashCode();
    }

}

